

#include "UftServer.h"
#include "UfPacket.h"
#include "UfServerNode.h"
#include "logging.h"
#include "tools/dump.h"

UftServer::UftServer()
    : mSock(tools::CSocket::eSocketType_UDP)
{
}

UftServer::~UftServer()
{
}

int UftServer::stop()
{
    mServerRunning = false;
    return 0;
}

int UftServer::start(int port)
{
    mSock.Close();
    mSock.Create();
    // mSock.SetHostIP("0.0.0.0");
    // mSock.SetHostPort(port);
    mSock.Bind(port);

    ILOG() << "server started.";
    mServerRunning = true;

    char    buffer[65536];
    int     timeout = 500;
    while (mServerRunning) {
        int ret = 0;
        if (timeout <= 0)
            timeout = 1;
        ret = mSock.Recv(buffer, sizeof(buffer), timeout);
        if (ret < 0) {
            ILOG() << mSock.GetErrorMessage();
            break;
        }


        if (mClients.size() > 0) {
            std::list<UfServerNode*>::iterator  it;
            for (it = mClients.begin(); it != mClients.end();) {
                if ((*it)->isValid()) {
                    (*it)->checkTimeout();
                }
                // check again.
                if ((*it)->isValid()) {
                    int ms = (*it)->getNearestMs();
                    if (timeout == 0) {
                        timeout = ms;
                    } else {
                        if (timeout > ms)
                            timeout = ms;
                    }
                    it++;
                } else {
                    ILOG() << "erase client. " << ((*it)->sid());
                    delete *it;
                    it = mClients.erase(it);
                    ILOG() << mClients.size() << " client left.";
                }
            }
        }

        if (ret == 0) {
            continue;
        }

        // ret > 0
        if (!UfPacket::isValidPacket(buffer, ret)) {
            // tools::dump(buffer, ret);
            // ignore.
            ILOG() << "Unknown packet. ignore.";
            continue;
        }

        Archive ar;
        ar.fromBuffer(buffer, ret);
        UfPacket packet(ar);
        // tools::dump(&packet, sizeof(packet));

        int sid = packet.sessionId;
        std::list<UfServerNode*>::iterator  it;
        for (it = mClients.begin(); it != mClients.end(); it++) {
            if ((*it)->sid() == sid)
                break;
        }

        if (it != mClients.end() && (*it)->isValid()) {
            (*it)->parsePacket(buffer, ret);
        } else {
            if (it != mClients.end()) {
                ILOG() << "erase client. " << ((*it)->sid());
                delete *it;
                mClients.erase(it);
                ILOG() << mClients.size() << " clients left.";
            }

            if (packet.action == UF_HELLO) {
                ILOG() << "received HELLO";
                UfServerNode* client = new UfServerNode(mSock);
                client->parsePacket(buffer, ret);
                mClients.push_back(client);
                ILOG() << "new client arrival.";
            } else {
                // ignore.
                ILOG() << "invalid packet. ignore.";
            }
        }
    }
    return 0;
}


